AddCSLuaFile( "cl_init.lua" )
AddCSLuaFile( "shared.lua" )
include('shared.lua')

ENT.wander = 1
ENT.pain = 1
ENT.Alerted     = false
ENT.bleeds      = 1
ENT.Grenades    = 2
ENT.MeleeAttacking = true
ENT.StartHealth = 100
ENT.PlayerFriendly = 1
ENT.Commander = false
ENT.hurtsound1 = Sound("clonetrooper/hurt01.wav")
ENT.hurtsound2 = Sound("clonetrooper/hurt02.wav")
ENT.hurtsound3 = Sound("clonetrooper/hurt03.wav")
ENT.hurtsound4 = Sound("clonetrooper/hurt04.wav")
ENT.alert1     = Sound("clonetrooper/attack1.wav")
ENT.alert2     = Sound("clonetrooper/attack2.wav")
ENT.alert3     = Sound("clonetrooper/attack3.wav")
ENT.idle1      = Sound("clonetrooper/idle1.wav")
ENT.idle2      = Sound("clonetrooper/idle2.wav")
ENT.idle3      = Sound("clonetrooper/idle3.wav")
ENT.idle4      = Sound("clonetrooper/idle4.wav")
ENT.idle5      = Sound("clonetrooper/idle5.wav")
ENT.attack1    = Sound("clonetrooper/attack1.wav")
ENT.attack2    = Sound("clonetrooper/attack2.wav")
ENT.attack3    = Sound("clonetrooper/attack3.wav")
ENT.die1     = Sound("clonetrooper/die1.wav")
ENT.die2     = Sound("clonetrooper/die2.wav")
ENT.die3     = Sound("clonetrooper/die3.wav")
ENT.cover    = Sound("clonetrooper/cover.wav")
ENT.seen_grenade = true
ENT.TakingCover = false
ENT.FindingLOS  = false
ENT.CanSeeEnemy = false
ENT.TimeToTakeCover = 0
ENT.OutOfAmmo = false
ENT.GotACloseOne = false
ENT.dead = false
ENT.speaktime = 0

function ENT:Initialize()
   if self:GetActiveWeapon() == nil then
   	self:GetOwner():PrintMessage( HUD_PRINTNOTIFY, "This entity needs a weapon!" )
	self:Give("weapon_smg1")
   end

   self:SetModel( "models/SGG/Starwars/clone_commando.mdl" )
   
   self:SetHullType( HULL_HUMAN )
   self:SetHullSizeNormal();
   self:SetSolid( SOLID_BBOX )
   self:SetMoveType( MOVETYPE_STEP )
   self:CapabilitiesAdd( CAP_MOVE_GROUND | CAP_OPEN_DOORS | CAP_SQUAD | CAP_ANIMATEDFACE | CAP_USE_WEAPONS | CAP_SQUAD | CAP_DUCK | CAP_MOVE_SHOOT | CAP_TURN_HEAD | CAP_USE_SHOT_REGULATOR | CAP_AIM_GUN )
   self:SetMaxYawSpeed( 5000 )

   self.Friends = {"npc_sgg_clonetrooper", "npc_sgg_clonecommando" }
   self.Scary_Things = { "npc_combinedropship", "npc_combinegunship", "npc_helicopter", "npc_strider", "npc_sniper" }
  
   //Sets the entity values
   self:SetHealth(self.StartHealth)
   self:SetEnemy(NULL)
   self:Fire("setsquad","Clonetrooper"..math.random(1,4).."Squad",0)
end
   
function ENT:OnTakeDamage(dmg)
   if (self.TakingCover == false) then
   	self:SetSchedule(SCHED_SMALL_FLINCH)
   end
   self:SpawnBlood(dmg)
   self:SetHealth(self:Health() - dmg:GetDamage())
   //if math.random(4) == 1 then
   if math.random(4) == 1 then
	print("Got Hurt!!!")
	self:StopSpeechSounds()
	local sound_seed = math.random(1,7)
	if sound_seed == 1 then
	self:EmitSound( self.hurtsound1)
	elseif sound_seed == 2 then
	self:EmitSound( self.hurtsound2)
	elseif sound_seed == 3 then
	self:EmitSound( self.hurtsound3)
	elseif sound_seed == 4 then
	self:EmitSound( self.hurtsound4)
	end	
	//self:SetSchedule(SCHED_ALERT_FACE)
   end
   if dmg:GetAttacker():GetClass() != self:GetClass() && math.random(1,25) == 1 then
   	self:ResetEnemy()
   	self:AddEntityRelationship( dmg:GetAttacker(), 1, 10 )
   	self:SetEnemy(dmg:GetAttacker())
   	self:CallForHelp()
   end
   if (self.TakingCover == false) || self.Alerted == false then
   	self.TakingCover = true
	print( "Take Cover, they shot me!" );
   	self:SetSchedule(SCHED_TAKE_COVER_FROM_ENEMY)
   end
   self.Alerted = true
   if self:Health() <= 0 && self.dead == false then //run on death	
	self.dead = true;
	print("DIED!!!")
	self:KilledDan()
   end
end


function ENT:Think()

local function setmeleefalse()
	self.MeleeAttacking = false
end

local function Attack_Melee()
	local entstoattack = ents.FindInSphere(self:GetPos() + self:GetForward()*75,74)
	if entstoattack != nil then
		self:EmitSound( "physics/body/body_medium_impact_hard"..math.random(1,6)..".wav", 400, 100)
		for _,v in pairs(entstoattack) do
			if ( (v:IsNPC() || ( v:IsPlayer() && v:Alive())) && (v != self) || (v:GetClass() == "prop_physics")) then
				v:TakeDamage( 5, self )
				if v:IsPlayer() then
					v:ViewPunch(Angle(math.random(-1,1)*15,math.random(-1,1)*15,math.random(-1,1)*15))
				end 
			end
		end
	else
	self:EmitSound( "zombie/claw_miss1.wav", 400, 100)
	//add miss stuff here
	end
	timer.Create( "melee_done_timer" .. self.Entity:EntIndex( ), 0.25, 1, setmeleefalse )
end

	//print(self.TakingCover)

	if self:Health() > 0 then
		//play idle sounds every now and then
	      	local random_s = math.random(1,250)
		if random_s == 1 then
		self:StopSpeechSounds()
	      	self:EmitSound( self.idle1, 300, 100)
		elseif random_s == 2 then
		self:StopSpeechSounds()
	      	self:EmitSound( self.idle2, 300, 100)
		elseif random_s == 3 then
		self:StopSpeechSounds()
	      	self:EmitSound( self.idle3, 300, 100)
		elseif random_s == 4 then
		self:StopSpeechSounds()
	      	self:EmitSound( self.idle4, 300, 100)
		elseif random_s == 5 then
		self:StopSpeechSounds()
	      	self:EmitSound( self.idle5, 300, 100)
	end
		//print( "Think start" );
		//Get all the npc's and other entities.
		local enttable = ents.FindByClass("npc_*")
		local monstertable = ents.FindByClass("monster_*")
		table.Add(monstertable,enttable)//merge

		//sort through each ent.
		for _, x in pairs(monstertable) do
			if (!ents) then print( "No Entities!" ); return end
			if (x:GetClass() != self:GetClass() && x:GetClass() != "npc_grenade_frag" && x:IsNPC()) then
				if x:GetClass() != "npc_tank" && x:GetClass() != "npc_tank_turrent" && x:GetClass() != "npc_citizen" && x:GetClass() != "npc_barney" && x:GetClass() != "npc_eli" && x:GetClass() != "npc_monk"  && x:GetClass() != "npc_alyx"  && x:GetClass() != "npc_mossman" && x:GetClass() != "npc_vortigaunt" && x:GetClass() != "npc_dog" then
				x:AddEntityRelationship( self, 1, 10 )
				else
				x:AddEntityRelationship( self, 3, 10 )
				end
			end
		end
		
		//print( "Think end" );
   		//self:AddRelationship("player D_HT 10")
		if self.TakingCover == false then
			self:GetBoomers()//grenades are top priority.
			if(math.random(1,20) == 1) then
				self:FindCloseEnemies()//get guys close to me
			end
		end
		
		//Hit them.
		if self:GetEnemy() != nil then
			if (self:GetEnemy():GetPos():Distance(self:GetPos()) < 70) then
				if self.MeleeAttacking == false then
					self:SetSchedule( SCHED_MELEE_ATTACK1 )
					timer.Create( "melee_attack_timer" .. self.Entity:EntIndex( ), 0.25, 1, Attack_Melee )
					self.MeleeAttacking = true;
				end
			else
				self.MeleeAttacking = false
			end
		end
				
	end
	local friends = ents.FindByClass("npc_tank")
	for _, x in pairs(friends) do
		x:AddEntityRelationship( self, 3, 10 )
	end


	local friends = ents.FindByClass("npc_tank_turrent")
	for _, x in pairs(friends) do
		x:AddEntityRelationship( self, 3, 10 )
	end

	local friends = ents.FindByClass("npc_citizen")
	for _, x in pairs(friends) do
		x:AddEntityRelationship( self, 3, 10 )
	end 

	local friends = ents.FindByClass("npc_eli")
	for _, x in pairs(friends) do
		x:AddEntityRelationship( self, 3, 10 )
	end

	local friends = ents.FindByClass("npc_alyx")
	for _, x in pairs(friends) do
		x:AddEntityRelationship( self, 3, 10 )
	end

	local friends = ents.FindByClass("npc_monk")
	for _, x in pairs(friends) do
		x:AddEntityRelationship( self, 3, 10 )
	end

	local friends = ents.FindByClass("npc_barney")
	for _, x in pairs(friends) do
		x:AddEntityRelationship( self, 3, 10 )
	end
	
	local friends = ents.FindByClass("npc_mossman")
	for _, x in pairs(friends) do
		x:AddEntityRelationship( self, 3, 10 )
	end

	local friends = ents.FindByClass("npc_vortigaunt")
	for _, x in pairs(friends) do
		x:AddEntityRelationship( self, 3, 10 )
	end

	local friends = ents.FindByClass("npc_dog")
	for _, x in pairs(friends) do
		x:AddEntityRelationship( self, 3, 10 )
	end
	
	local friends = ents.FindByClass("player")
	for _, x in pairs(friends) do
		x:AddEntityRelationship( self, 3, 10 )
	end
end
   
function ENT:SelectSchedule()
if self:Health() > 0 then
	//makes it never run out of ammo... :D
	self:GetActiveWeapon():SetClip1(45)
	haslos = self:HasLOS()
	//local objectives = ents.FindByClass("objective ent")

	local distance = 0
	local enemy_pos = 0
	if self:GetEnemy() == nil then//no enemy
		self:FindEnemyDan()
		//print( "No Enemy!" );
		if math.random(1,2) == 1 then
		self:SetSchedule(SCHED_COMBAT_PATROL)//patrol# 
		elseif math.random(1,4) == 1 then
		self:SetSchedule(SCHED_PATROL_WALK )
		elseif math.random(1,2) == 1 then
		self:SetSchedule( SCHED_IDLE_WALK)
		else
		self:SetSchedule( SCHED_IDLE_STAND )
		end
		self.TakingCover = false
	else
		//print( "Enemy!" );
		//print(self:GetEnemy())
		enemy_pos = self:GetEnemy():GetPos()
		distance = self:GetPos():Distance(enemy_pos)
		//distance = 4000
	        if distance > 4000 then//if too far away
			print( "Find him!" );
			self:SetSchedule(SCHED_CHASE_ENEMY)//move to enemy
		elseif distance < 4000 && distance > 400 then//if in reasonable distance
			if self:Health() < (self.StartHealth*0.25) then//if damaged > 75% and not in cover
				self.TakingCover = true
				print( "Take Cover, I'm hurt!" );
				self:SetSchedule(SCHED_TAKE_COVER_FROM_ENEMY)//take cover
			else
				self.TakingCover = false
	      			local randomsound = math.random(1,4)
				
				if CurTime() > self.speaktime then
				self.speaktime = CurTime() + 6
				if randomsound == 1 then
				self:StopSpeechSounds()
	      			self:EmitSound( self.attack1)
				elseif randomsound == 2 then
				self:StopSpeechSounds()
	      			self:EmitSound( self.attack2)
				elseif randomsound == 3 then
				self:StopSpeechSounds()
	      			self:EmitSound( self.attack3)
				end
				end
				if haslos then //&& distance > 1000 then
					self:SetSchedule(SCHED_COMBAT_STAND)
				else
					if math.random(1,2) == 1 then
					self:SetSchedule(SCHED_ESTABLISH_LINE_OF_FIRE)//move to shoot enemy
					else
					self:SetSchedule(SCHED_CHASE_ENEMY)//otherwise go to them.
					end
				end
					
				if math.random(1,80) < 3 then
					self:StopSpeechSounds()
					self:EmitSound("clonetrooper/cover.wav")
					self:SetSchedule(SCHED_RELOAD) //give the ILLUSION of reloading. :D
				end
				//self:SetSchedule(SCHED_RANGE_ATTACK1)
			end
		else//if too close 
			if (haslos == true) then
				if self.TakingCover == false then
				self.TakingCover = true
				self:SetSchedule( SCHED_TAKE_COVER_FROM_ENEMY )//avoid melee attack
				else
				//self.TakingCover = false
				self:SetSchedule(SCHED_COMBAT_STAND )
				end
			else	
				self.TakingCover = false
				self:SetSchedule(SCHED_CHASE_ENEMY)//move to shoot enemy
			end
		end
	end
end
end

function ENT:FindEnemyDan()
	local MyNearbyTargets = ents.FindInCone(self:GetPos(),self:GetForward(),7000,68)
	//local ClosestDistance = 3000
	if (!MyNearbyTargets) then print( "No Targets!" ); return end
	for k,v in pairs(MyNearbyTargets) do
	    if v:Disposition(self) == 1 || (v:IsPlayer() && self.PlayerFriendly == 0 && GetConVarNumber("ai_ignoreplayers") == 0) then
	    //if (v:GetClass() == "npc_*" || v:GetClass() == "monster_*") && v:GetClass() != self:GetClass() && v:GetClass() != "npc_tank" && v:GetClass() != "npc_tank_turrent" then
		print(v:GetClass())
		self:StopSpeechSounds()
		self:ResetEnemy()
   		self:AddEntityRelationship( v, 1, 10 )
	      	self:SetEnemy(v)
		local distance = self:GetPos():Distance(v:GetPos())
	      	local randomsound = math.random(1,5)
		//self:SetSchedule(SCHED_ALERT_FACE)
		//alerted
		if self.Alerted == false then
		if (distance > 270) then
			if randomsound == 1 then
	      		self:EmitSound( self.alert1)
			elseif randomsound == 2 then
	      		self:EmitSound( self.alert2)
			elseif randomsound == 3 then
	      		self:EmitSound( self.alert3)
			end
		else
			if randomsound == 1 then
	      		self:EmitSound( self.alert1)
			elseif randomsound == 2 then
	      		self:EmitSound( self.alert2)
			elseif randomsound == 3 then
	      		self:EmitSound( self.alert3)
			end
		end
		end
		self.Alerted = true
	      	return
	    end
	end
	//if ClosestDistance == 4000 then
	self:SetEnemy(NULL)
	//end
end

function ENT:StopSpeechSounds()
   self:StopSound(self.alert1)
   self:StopSound(self.alert2)
   self:StopSound(self.alert3)
   self:StopSound(self.attack1)
   self:StopSound(self.attack2)
   self:StopSound(self.attack3)
end

function ENT:StopHurtSounds()
   self:StopSound(self.hurtsound1)
   self:StopSound(self.hurtsound2)
   self:StopSound(self.hurtsound3)
   self:StopSound(self.hurtsound4)
end

function ENT:SpawnBlood(dmg)
   if (self.bleeds > 0) then
   	local bloodeffect = ents.Create( "info_particle_system" )
   	bloodeffect:SetKeyValue( "effect_name", "blood_impact_red_01" )
        bloodeffect:SetPos( dmg:GetDamagePosition() ) 
	bloodeffect:Spawn()
	bloodeffect:Activate() 
	bloodeffect:Fire( "Start", "", 0 )
	bloodeffect:Fire( "Kill", "", 0.1 )
   end
end

function ENT:GetBoomers()
	local nearbygrenades = ents.FindByClass("npc_grenade_frag")
	for k,v in pairs(nearbygrenades) do
	    if self:GetPos():Distance(v:GetPos()) < 400 then
		self:StopSpeechSounds()
		self:ResetEnemy()
   		self:AddEntityRelationship( v, 3, 10 )
	      	//self:SetEnemy(v)
	      	//local randomsound = math.random(1,10)
		//if randomsound == 1 then
	      	//self:EmitSound( self.alert1 )
		//elseif randomsound == 2 then
	      	//self:EmitSound( self.alert2 )
		//elseif randomsound == 3 then
	      	//self:EmitSound( self.alert3 )
		//elseif randomsound == 4 || randomsound == 5 || randomsound == 6 then
	      	//self:EmitSound( self.alert1)
		//else
	      	//self:EmitSound( self.alert2)
		//end
		self.seen_grenade = true
		self.TakingCover = true
		self:SetSchedule(SCHED_HIDE_AND_RELOAD)
		return
	    end
	end
end

function ENT:KilledDan()
	/*I Took some of silverlan's code for ragdolling, cause I didn't want to recode it :P*/
	//emit cry of death
   	self:StopSpeechSounds()
	self:StopHurtSounds()
	local deathseed = math.random(1,11)
	if     deathseed == 1 then
	  self:EmitSound( self.die1, 450, 100)
	elseif deathseed == 2 then
	  self:EmitSound( self.die2, 450, 100)
	end

	//create ragdoll
	local ragdoll = ents.Create( "prop_ragdoll" )
	ragdoll:SetModel( self:GetModel() )
	ragdoll:SetPos( self:GetPos() )
	ragdoll:SetAngles( self:GetAngles() )
	ragdoll:Spawn()
	ragdoll:SetSkin( self:GetSkin() )
	ragdoll:SetColor( self:GetColor() )
	ragdoll:SetMaterial( self:GetMaterial() )
	
	//my code
	undo.ReplaceEntity(self,ragdoll)
	cleanup.ReplaceEntity(self,ragdoll)

	//ignight ragdoll if on fire.
	if self:IsOnFire() then ragdoll:Ignite( math.Rand( 8, 10 ), 0 ) end

	//position bones the same way.
        for i=1,128 do
		local bone = ragdoll:GetPhysicsObjectNum( i )
		if ValidEntity( bone ) then
			local bonepos, boneang = self:GetBonePosition( ragdoll:TranslatePhysBoneToBone( i ) )
			bone:SetPos( bonepos )
			bone:SetAngle( boneang )
		end
	end
	if( GetConVarNumber("ai_keepragdolls") == 0 ) then
		ragdoll:SetCollisionGroup( 1 )//COLLISION_GROUP_DEBRIS )
		ragdoll:Fire( "FadeAndRemove", "", 7 )
	end
	self:Remove()
end

function ENT:CallForHelp()
	local AllOfMyFriends = ents.FindByClass(self:GetClass())
	for _,x in pairs(AllOfMyFriends) do
		if self:GetPos():Distance(x:GetPos()) < 4000 then
			if x.Alerted == false then
   			x:ResetEnemy()
   			x:AddEntityRelationship( self:GetEnemy(), 1, 10 )
			x:SetEnemy(self:GetEnemy())
			x:SetSchedule(SCHED_CHASE_ENEMY)
			end
		end
	end
end

function ENT:ResetEnemy()
end

function ENT:FindCloseEnemies()
	local MyNearbyTargets = ents.FindInCone(self:GetPos(),self:GetForward(),300,45)
	//local ClosestDistance = 3000
	if (!MyNearbyTargets) then print( "No Targets!" ); return end
	for k,v in pairs(MyNearbyTargets) do
	    if v:Disposition(self) == 1 || v:IsPlayer() then
		print(v:GetClass())

		self:StopSpeechSounds()
		self:ResetEnemy()
   		self:AddEntityRelationship( v, 1, 10 )
	      	self:SetEnemy(v)

   		if (self.TakingCover == false) || self.Alerted == false then
   			self.TakingCover = true
   			self:SetSchedule(SCHED_TAKE_COVER_FROM_ENEMY)
		end

	      	local randomsound = math.random(1,90)
		
		self.Alerted = true
	      	return
	    end
	end
end

function ENT:OnRemove()
	timer.Remove("melee_attack_timer" .. self.Entity:EntIndex( ))
	timer.Remove("melee_done_timer" .. self.Entity:EntIndex( ))
end

function ENT:HasLOS()
	if self:GetEnemy() != nil then
	//local shootpos = self:GetAimVector()*(self:GetPos():Distance(self:GetEnemy():GetPos())) + self:GetPos()
	//local shootpos = self:GetEnemy():GetPos()
	local tracedata = {}

	tracedata.start = self:GetPos()
	tracedata.endpos = self:GetEnemy():GetPos()
	tracedata.filter = self

	local trace = util.TraceLine(tracedata)
	if trace.HitWorld == false then
		print("returned true!")
		return true
	else 
		return false
	end
	end
	print ("no enemy!")
	return false
end